//[pt,dx,dz,dt]=acoustic(vel,tf,fc,spos,dx,dz,dt)
//[pt[,dx,dz,dt]]=acoustic(vel,tf,fc,spos[,dx,dz][,dt])
//////////////////////////////////////////////////////
//                                                  //
//  Scilab program to simulate forward propagation  //
//  of acoustic waves with absorbing boundary       //
//  conditions where p is the wavefield, s is the   //
//  source, and v is the velocity field:            //
//                                                  //
//                      2  __ 2                     //
//             P   =  v    \/   P + S               // 
//              tt                                  //
//                                                  //
//////////////////////////////////////////////////////
// vel  :Velocity distribution (matrix which represents
//      :distribution of velocity as function of offset x 
//      :and depth z.  Increasing offset and depth goes
//      :as the increasing indices of the matrix vel).
// tf   :Final time (initial time is zero)
// fc   :Center frequency of wavelet (derivative of gaussian)
// spos :source postion which is a 2-vector of integers 
//      :where 1<=spos(1)<=nr, 1<=spos(2)<=nc 
//      :and [nr,nc]=size(vel).
// dx   :Sampling step in offset 
// dz   :Sampling step in depth
// dt   :Sampling step in time.  
// ntbl :Name table containing names of all the files 
//      :created containing data
//
//The parameters dx, dz, and dt are optional and are
//calculated automatically, when not specified, to satisfy
//stability conditions and to impose an acceptable level
//of numerical dispersion.
//
//!
//author: C. Bunks     date: 29-Oct-90

   [lhs,rhs]=argn(0);
   lines(0);

//velocity parameters

   [nr,nc]=size(vel);
   vmax=maxi(vel);vmin=mini(vel);

//default check

   if rhs=4 then,//auto calculation of dx, dz, and dt
      dx=vmin/(16*fc);
      dz=dx;
      dmin=mini([dx,dz]);dmax=maxi([dx,dz]);   
      dt=.95*dmin/(vmax*sqrt(2));//stability condition 
   end,
   if rhs=5 then,//auto calculation of dx and dz
      dx=vmin/(16*fc);
      dz=dx;
      dmin=mini([dx,dz]);dmax=maxi([dx,dz]);   
   end,
   dmin=mini([dx,dz]);dmax=maxi([dx,dz]);   
   if rhs=6 then,//auto calculation of dt
      dt=.95*dmin/(vmax*sqrt(2));//stability condition 
   end,

//inform user of default choices

   write(%io(2),' '),
   write(%io(2),' CHOICES OF DX, DZ, AND DT:'),
   print(6,[dx,dz,dt]),
   write(%io(2),' '),

//ERROR CHECKING
//source location

   eflag='on';
   if 1<=spos(1) then, if spos(1)<=nr then,
   if 1<=spos(2) then, if spos(2)<=nc then,
      eflag='off';
   end,end,
   end,end,
   if eflag='on' then,
      write(%io(2),'                               '),
      write(%io(2),'*************ERROR*************');
      write(%io(2),'                               '),
      write(%io(2),' SOURCE POSITION OUT OF BOUNDS ');
      write(%io(2),'                               '),
      write(%io(2),'*************ERROR*************');
      write(%io(2),'                               '),
      error('sim.bas'),
   end,

//space discretization

   if dmax>vmin/(15*fc) then,
      write(%io(2),'                                       '),
      write(%io(2),'****************WARNING****************');
      write(%io(2),'                                       '),
      write(%io(2),' NUMERICAL DISPERSION LIKELY           '),
      write(%io(2),' VARIABLES SHOULD SATISFY:             '),
      write(%io(2),'                                       '),
      write(%io(2),'     max([dx,dz]) < vmin/(15*fc)       '),
      write(%io(2),'                                       '),
      write(%io(2),'****************WARNING****************');
      write(%io(2),'                                       '),
   end,

//time discretization and stability check
//           v*dt/dx < 1/sqrt(2)

   if (vmax*dt/dmin)>(1/sqrt(2)) then,
      write(%io(2),'                                       '),
      write(%io(2),'*****************ERROR*****************');
      write(%io(2),'                                       '),
      write(%io(2),' UNSTABLE CHOICES: vel, dt, dx, and dz '),
      write(%io(2),' VARIABLES MUST SATISFY:               '),
      write(%io(2),'                                       '),
      write(%io(2),'    max(vel)*dt*sqrt(2) < min(dx,dz)   '),
      write(%io(2),'                                       '),
      write(%io(2),'*****************ERROR*****************');
      write(%io(2),'                                       '),
      error('sim.bas'),
   end,
   t=0:dt:tf;

//pre-calculation

   v2dt=(dt*dt)*(vel.*vel);
   zr=0*ones(1,nc);zc=0*ones(nr,1);

//integrate forward 

//   unit=file('open','pt.dat','unknown','unformatted');
   pt=[];
   pkm1=0*ones(vel);pkm2=0*ones(vel);//initial conditions
   for tk=t,
      src=shot(tk,fc);
      pk=integrate(tk,pkm1,pkm2,src,spos);
      pt=[pt;pk];
//      writb(unit,pk);
      pkm2=pkm1;pkm1=pk;
   end,
//   file('rewind',unit);
//   pt=readb(unit,nr*maxi(size(t)),nc);
//   file('close',unit);

//end

//[utp1]=integrate(t,ut,utm1,src,spos)
//[utp1]=integrate(t,ut,utm1,src,spos)
//compute second order time update of acoustic wave equation
//(with absorbing boundaries)
// t     :current time
// ut    :wavefield at time t
// utm1  :wavefield at time t-dt
// src   :source value at time t
// spos  :source position
// utp1  :wavefield at time t+dt
//
//!
//author: C. Bunks     date: 29-OCT-90

   write(%io(2),'t='+string(t));

//calculate laplacian in the interior of the medium

   utp1= 2*ut...
        -utm1...
        +v2dt.*(([ut(:,2:nc) zc]+[zc ut(:,1:nc-1)]-2*ut)/dx**2...
               +([ut(2:nr,:);zr]+[zr;ut(1:nr-1,:)]-2*ut)/dz**2);

//calculate boundary conditions on edges  (fix velocities)
//(see paper by Reynolds, Geophysics, v. 43, 1978, pp1099-1110)

//right side boundary
   ua=ut(:,nc-1);ub=ut(:,nc);uc=utm1(:,nc-2);ud=utm1(:,nc-1);
   utp1(:,nc)=(ua+ub-ud)-(dt/dx)*vel(:,nc).*(ub-ua+uc-ud);

//left side boundary
   ua=ut(:,2);ub=ut(:,1);uc=utm1(:,3);ud=utm1(:,2);
   utp1(:,1)=(ua+ub-ud)-(dt/dx)*vel(:,1).*(ub-ua+uc-ud);

//bottom boundary
   ua=ut(nr-1,:);ub=ut(nr,:);uc=utm1(nr-2,:);ud=utm1(nr-1,:);   
   utp1(nr,:)=(ua+ub-ud)-(dt/dz)*vel(nr,:).*(ub-ua-ud+uc);

//top boundary (absorbing or free)
   ua=ut(2,:);ub=ut(1,:);uc=utm1(3,:);ud=utm1(2,:);   
   utp1(1,:)=(ua+ub-ud)-(dt/dz)*vel(1,:).*(ub-ua-ud+uc);

//calculate boundary conditions at corners
   utp1(1,1)=ut(1,1)+((dt/dx)*vel(1,1))*(ut(2,2)-ut(1,1));
   utp1(1,nc)=ut(1,nc)+((dt/dx)*vel(1,nc))*(ut(2,nc-1)-ut(1,nc));
   utp1(nr,1)=ut(nr,1)+((dt/dx)*vel(nr,1))*(ut(nr-1,2)-ut(nr,1));
   utp1(nr,nc)=ut(nr,nc)+((dt/dx)*vel(nr,nc))*(ut(nr-1,nc-1)-ut(nr,nc));

//add in source
   sz=spos(1);sx=spos(2);
   utp1(sz,sx)=utp1(sz,sx)+dt**2*src;

//end

//[dg]=shot(t,fc)
//[dg]=shot(t,fc)
//calculate shot values as a function of time
//as the derivative of a gaussian:
//
//   g=exp(-(t-m)**2/(2*sigma**2))
//   dg=-g*(t-m)/sigma**2
//
//Center frequency for the derivative of the gaussian is
//at fc=1/(2*m). The ratio of the minimum velocity (vm) 
//to center frequency (fc) (i.e., the smallest spatial wavelength)
//should be between 10 and 20 times greater than the largest 
//spatial discretization.  Here we take the factor to be 15:
//
//              vm/fc = 2*m*vm > 15*maxi(dx,dz)
//or
//                  m = 7.5*maxi(dx,dz)/mini(vel)
//
// t  :current time
// fc :center frequency of the wavelet
// dg :derivative of a gaussian at time t
//
//!
//author: C. Bunks     date: 29-OCT-90

   m=1/(2*fc);
   sig=m/4;
   sig2=sig**2;
   g=exp(-(t-m)**2/(2*sig2))/sqrt(2*%pi*sig2);
   dg=-g*(t-m)/sig2;

//end

//[pt]=get_data(ntbl,entry)
//Search for a data file written on disk
// ntbl  :table of file names (first two entries give 
//       :data dimensions)
// entry :integer giving the entry in the table-2
// pt    :returned data file

   ts=maxi(size(ntbl));
   nr=evstr(ntbl(1));
   nc=evstr(ntbl(2));
   if entry<=ts-2 then,
      filename=ntbl(entry+2);
      unit=file('open',filename,'unknown');
      pt=read(unit,nr,nc);
      file('close',unit);
      plot2d(pt,'agc',[0,%pi/4],'x');
   else,
      write(%io(2),' '),
      write(%io(2),' Table Entry to Large...Max Value='+string(ts-2)),
      write(%io(2),' '),
   end,

//end

